package com.sneakxy.mybase4j.platform.controller;

import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.subject.Subject;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.sneakxy.mybase4j.base.controller.BaseController;
import com.sneakxy.mybase4j.platform.beans.Account;
import com.sneakxy.mybase4j.platform.beans.Dict;
import com.sneakxy.mybase4j.platform.beans.Launcher;
import com.sneakxy.mybase4j.platform.beans.LauncherSetting;
import com.sneakxy.mybase4j.platform.beans.LauncherSettingId;
import com.sneakxy.mybase4j.platform.beans.LoginLog;
import com.sneakxy.mybase4j.platform.beans.Menu;
import com.sneakxy.mybase4j.platform.service.IAccountService;
import com.sneakxy.mybase4j.platform.service.IDictService;
import com.sneakxy.mybase4j.platform.service.ILauncherService;
import com.sneakxy.mybase4j.platform.service.ILauncherSettingService;
import com.sneakxy.mybase4j.platform.service.ILoginLogService;
import com.sneakxy.mybase4j.platform.service.IMenuService;
import com.sneakxy.mybase4j.platform.service.IRouterService;
import com.sneakxy.mybase4j.util.Response;

/**
 * 首页，登录等操作
 * @author 潜行的青衣
 * @see
 */
@Controller
public class IndexController extends BaseController {

	@Resource
	private IRouterService routerService;
	
	@Resource
	private IMenuService menuService;
	
	@Resource
	private ILoginLogService loginLogService;
	
	@Resource
	private ILauncherService launcherService;
	
	@Resource
	private IDictService dictService;
	
	@Resource
	private PasswordEncoder passwordEncoder;
	
	@Resource
	private IAccountService accountService;
	
	@Resource
	private ILauncherSettingService launcherSettingService;
	
	@RequestMapping({"/", "/admin"})
	public String index() {
		if(SecurityUtils.getSubject().isAuthenticated() || SecurityUtils.getSubject().isRemembered()) {
			return "redirect:/index.html";
		}
		return "redirect:/login.html";
	}
	
	@RequestMapping("/api/accessed")
	@ResponseBody
	public Response accessed(HttpServletResponse response) {
		response.setStatus(HttpServletResponse.SC_FORBIDDEN);
		return new Response(false, "403");
	}
	
	@RequestMapping("/api/unauthorized")
	@ResponseBody
	public Response unauthorized(HttpServletResponse response) {
		response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
		return new Response(false, "401");
	}
	
	@RequestMapping("/api/index/init")
	@ResponseBody
	public Map<String, Object> init() {
		Account account = (Account) this.getLoginAccount();
		Map<String, Object> result = new LinkedCaseInsensitiveMap<Object>(3);
		//路由
		result.put("routers", routerService.findByAccountId(account.getId()));
		//菜单
		result.put("menus", menuService.findByAccountId(account.getId(), Menu.MENU_TYPE_SYSTEM));
		//自动启动
		result.put("launchers", this.launcherService.findAllLauncherModules(account.getId()));
		return result;
	}
	
	@RequestMapping("/api/login")
	@ResponseBody
	public Response login(
			HttpServletRequest request,
			String username, String password, boolean rememberMe) {
		Response result = new Response(true);
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username, password);
		token.setHost(request.getRemoteAddr());
		token.setRememberMe(rememberMe);
		LoginLog log = new LoginLog();
		log.setLogintime(DateFormatUtils.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss"));
		log.setAccount(username);
		try {
			subject.login(token);
			log.setStatus(LoginLog.STATUS_SUCCESS);
		} catch(UnknownAccountException e) {
			result.setSuccess(false);
			result.setMessage(0);
			log.setStatus(LoginLog.STATUS_UNKNOWN_ACCOUNT);
		} catch(IncorrectCredentialsException e) {
			result.setSuccess(false);
			result.setMessage(1);
			log.setStatus(LoginLog.STATUS_INCORRECT_CREDENTIALS);
		} catch(LockedAccountException e) {
			result.setSuccess(false);
			result.setMessage(2);
			log.setStatus(LoginLog.STATUS_LOCKED_ACCOUNT);
		}
		loginLogService.save(log);
		return result;
	}
	
	@RequestMapping("/api/logout")
	@ResponseBody
	public Response logout() {
		SecurityUtils.getSubject().logout();
		return new Response(true);
	}
	
	@RequestMapping("/api/perms")
	@ResponseBody
	public Response perms(HttpServletRequest request) {
		Map<String, Boolean> result = new LinkedHashMap<String, Boolean>();
		Iterator<Entry<String, String[]>> it = request.getParameterMap().entrySet().iterator();
		Entry<String, String[]> entry = null;
		while(it.hasNext()) {
			entry = it.next();
			result.put(entry.getKey(), this.isPermitted(entry.getValue()[0]));
		}
		return new Response(result);
	}
	
	@RequestMapping("/api/roles")
	@ResponseBody
	public Response roles(HttpServletRequest request) {
		Map<String, Boolean> result = new LinkedHashMap<String, Boolean>();
		Iterator<Entry<String, String[]>> it = request.getParameterMap().entrySet().iterator();
		Entry<String, String[]> entry = null;
		while(it.hasNext()) {
			entry = it.next();
			result.put(entry.getKey(), this.hasRole(entry.getValue()[0]));
		}
		return new Response(result);
	}
	
	@RequestMapping("/api/dict")
	@ResponseBody
	public Response dict(String[] values, boolean children) {
		Dict result = null;
		if(values != null) {
			result = this.dictService.findByValues(values, children);
		}
		return new Response(result != null, result);
	}
	
	@RequiresAuthentication
	@RequestMapping("/api/index/password")
	@ResponseBody
	public Response password(String oldPassword, String password) {
		Account account = (Account) this.getLoginAccount();
		Account old = this.accountService.findOne(account.getId());
		if(!this.passwordEncoder.matches(oldPassword, old.getPassword())) {
			return new Response(false, 1);
		}
		old.setPassword(this.passwordEncoder.encode(password));
		old = this.accountService.save(old);
		
		account.setPassword(old.getPassword());
		account.setUpdatetime(old.getUpdatetime());
		return new Response(true);
	}
	
	@RequiresAuthentication
	@RequestMapping("/api/index/launchers")
	@ResponseBody
	public Response launchers() {
		Account account = (Account) this.getLoginAccount();
		List<Launcher> result = this.launcherService.findAllLaunchers(account.getId());
		return new Response(result);
	}
	
	@RequiresAuthentication
	@RequestMapping("/api/index/launcher")
	@ResponseBody
	public Response launcher(String lid, boolean enable) {
		Account account = (Account) this.getLoginAccount();
		Launcher launcher = this.launcherService.findOne(lid);
		if(launcher != null && launcher.isManual()) {
			LauncherSettingId id = new LauncherSettingId(account.getId(), lid);
			this.launcherSettingService.delete(id);
			LauncherSetting ls = new LauncherSetting(id);
			ls.setEnable(enable);
			ls.setNew(true);
			ls = this.launcherSettingService.save(ls);
		}
		return new Response(true);
	}
	
}
